<?php

namespace StudyBuddy\I18n;

use \StudyBuddy\CacheCallback;

/**
 * Simple translator class
 * for getting translated messages
 * with option to use fallback value
 * and option to use placeholders in translation strings
 * and have these placeholders replaced at time
 * of returning translated string
 *
 * This class is serializable so the object
 * can be stored in cache or in session for very
 * efficient and fast object creation
 *
 */
class Translator implements \Serializable, \ArrayAccess, \StudyBuddy\Interfaces\Translator {

    /**
     *
     * Array of messages
     * in the form of associative array
     * where keys are strings
     * and values are the translations of the string
     *
     * @var array
     */
    protected $aMessages = array();

    /**
     * Name of locate
     * This object holds array of messages
     * for this locale
     *
     * @var string
     */
    protected $locale;

    /**
     * Factory method
     * This is a preferred method for 
     * instantiating this object
     * as it will return object that contains
     * catalog that includes current locale merged
     * with fallback language locale merged
     * with default catalog
     * 
     * @param \StudyBuddy\Registry $oRegistry
     */
    public static function factory(\StudyBuddy\Cache $Cache, $locale) {
        if (!\is_string($locale)) {
            throw new \StudyBuddy\DevException('Param $locale must be a string. Was: ' . gettype($locale));
        }

        $fallback = null;

        if (strlen($locale) > 3) {
            d('going to also use lang fallback for $locale: ' . $locale);

            $fallback = substr($locale, 0, -strlen(strrchr($locale, '_')));
        }

        $default = STUDYBUDDY_DEFAULT_LOCALE;
        d('$default: ' . $default . ' $locale: ' . $locale . ' $fallback: ' . $fallback);

        $o = new static();
        $o->setLocale($locale);

        /**
         * Get the XLIFF object for this locale,
         * one for fallback if different from this locale
         * one for default if different
         * from $locale and from $fallback
         */
        $o->addCatalog($Cache->get('xliff_' . $locale));

        if (!empty($fallback) && ($fallback !== $locale)) {
            $o->addCatalog($Cache->get('xliff_' . $fallback));
        }

        if (!empty($default) && ($default !== $fallback) && ($default !== $locale)) {
            $o->addCatalog($Cache->get('xliff_' . $default));
        }

        return $o;
    }

    /**
     *
     * Enter description here ...
     * @param unknown_type $locale
     */
    public function setLocale($locale) {
        if (!\is_string($locale)) {
            throw new \StudyBuddy\DevException('Param $locale must be a string Was: ' . gettype($locale));
        }


        /* if(2 !== strlen($locale) && (!preg_match('/[a-z]{2}_[A-Z]{2}/', $locale))){
          throw new \InvalidArgumentException('Param $locale is invalid. Must be in a form on "en_US" format (2 letter lang followed by underscore followed by 2-letter country');
          } */

        $this->locale = $locale;

        return $this;
    }

    /**
     * (non-PHPdoc)
     * @see StudyBuddy\Interfaces.Translator::getLocale()
     */
    public function getLocale() {
        return $this->locale;
    }

    /**
     * (non-PHPdoc)
     * @see StudyBuddy\Interfaces.Translator::translate()
     */
    public function get($string, array $vars = null, $default = null) {
        $str = (!empty($this->aMessages[$string])) ? $this->aMessages[$string] : (is_string($default) ? $default : $string);

        return (!$vars) ? $str : strtr($str, $vars);
    }

    /**
     *
     * Add array of messages to current
     * $this->aMessages array
     * New array is merged with $this->aMessages
     * will override existing values
     * for same keys as $this->aMessages 
     * 
     * @param array $a
     */
    public function addArray(array $a) {
        $this->aMessages = array_merge($this->aMessages, $a);

        return $this;
    }

    /**
     *
     * Enter description here ...
     * @param \StudyBuddy\Interfaces\TranslatorCatalog $o
     */
    public function addCatalog(\StudyBuddy\Interfaces\Translator $o) {
        $a = $o->getMessages();

        $this->addArray($a);

        return $this;
    }

    /**
     * (non-PHPdoc)
     * @see Serializable::serialize()
     */
    public function serialize() {
        return \json_encode(array(
                    'aMessages' => $this->aMessages,
                    'locale' => $this->locale)
        );
    }

    /**
     * (non-PHPdoc)
     * @see Serializable::unserialize()
     */
    public function unserialize($serialized) {
        $a = \json_decode($serialized, true);
        $this->aMessages = $a['aMessages'];
        $this->locale = $a['locale'];
    }

    /**
     * (non-PHPdoc)
     * @see StudyBuddy\Interfaces.Translator::getMessages()
     */
    public function getMessages() {
        return $this->aMessages;
    }

    /**
     * (non-PHPdoc)
     * @see StudyBuddy\Interfaces.Translator::has()
     */
    public function has($string) {
        return array_key_exists($string, $this->aMessages);
    }

    public function offsetExists($offset) {
        return $this->has($offset);
    }

    public function offsetGet($offset) {
        return $this->get($offset, null, $offset);
    }

    public function offsetUnset($offset) {
        
    }

    public function offsetSet($offset, $value) {
        $this->aMessages[$offset] = $value;
    }

}
